﻿using log4net;
using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Linq;
using System.Text;
using Timesheet.Data.Infrastructure;
using Timesheet.Data.Repository;
using Timesheet.Domain;

namespace Timesheet.Service
{
    public class TimeSheetsService:ITimeSheetsService
    {
        private readonly ITimeSheetsRepository _Repository;
        private readonly ITimeSheetDetailsRepository _TimeSheetDetailsRepository;
        private readonly IUnitOfWork _UnitOfWork;
        private readonly IUserRepository _UserRepository;
        private readonly IUserService _userService;
        private readonly IProjectRepository _ProjRepository;
        private readonly ITeamDetailRepository _teamDetailRepository;
        public ILog Logger { get; private set; }

        public TimeSheetsService(ITimeSheetDetailsRepository timeSheetDetailsRepository,IUserRepository userRepository,
            ITimeSheetsRepository TimeSheetsRepository, IProjectRepository projectRepository, IUserService userService, ITeamDetailRepository teamDetailRepository,
            IUnitOfWork unitOfWork)
        {
            _Repository = TimeSheetsRepository;
            _UnitOfWork = unitOfWork;
            _UserRepository = userRepository;
            _TimeSheetDetailsRepository = timeSheetDetailsRepository;
            _ProjRepository = projectRepository;
            _teamDetailRepository = teamDetailRepository;
            _userService = userService;
        }

        #region ITimeSheetsService Members

        public IList<TimeSheets> GetTimeSheets()
        {
            return _Repository.GetAll().ToList();
        }
        public IList<TimeSheets> GetTimeSheets(string role,long prjID,long userID)
        {
            var lstMgrPrj = _ProjRepository.GetAll().Where(u => u.Active == true).Distinct().Select(u => u.PrjID);

            IDictionary<long, TimeSheets> listReturn = new Dictionary<long, TimeSheets>();
            var tmshQr = _Repository.GetQuery();
            if(prjID != -1)//not query 
            {
                tmshQr = tmshQr.Where(x => x.ProjectID == prjID);
            }
            var user = _UserRepository.GetById(userID);

            // Manager 
            var listManager = tmshQr.Where(x => (user.Manager && (x.Status == "1" || x.Status == "2" || x.Status == "3")))
                                .Distinct()
                                .ToList();

            foreach (var item in listManager)
            {
                item.Role = 3;
                listReturn.Add(item.Id, item);
            }
            var listCoord = tmshQr.Where(x => (user.Coordinator && (x.Status == "1" || x.Status == "2" || x.Status == "3")))
                              .Distinct()
                              .ToList();
            foreach (var item in listCoord)
            {
                if (!listReturn.ContainsKey(item.Id))
                {
                    item.Role = 2;
                    listReturn.Add(item.Id, item);
                }
            }

            var listCoordLeader = tmshQr.Where(x => (user.Coordinator && x.CreateBy == userID)).Distinct().ToList();

            foreach (var item in listCoordLeader)
            {
                if (!listReturn.ContainsKey(item.Id))
                {
                    item.Role = 2;
                    listReturn.Add(item.Id, item);
                }
            }

            var listLeader = tmshQr.Where(x=> (user.TeamLead && x.CreateBy == userID)).Distinct().ToList();
            if (user.TeamLead == true)
            {
                 var teamIds = _teamDetailRepository.GetQuery().Where(x => x.EmployerID == user.Id).Select(x => x.TeamID);
                 var timesheets = tmshQr.Where(p => teamIds.Contains(p.TeamID)).Distinct().ToList();
                 listLeader.AddRange(timesheets);
            }

            foreach (var item in listLeader)
            {
                if (!listReturn.ContainsKey(item.Id))
                {
                    item.Role = 1;
                    listReturn.Add(item.Id, item);
                }
            }
            return listReturn.Values.Where(u => lstMgrPrj.Contains(u.ProjectID)).OrderByDescending(p => p.From).ToList();

        }
        public bool CheckExist(TimeSheets entity)
        {
            return _Repository.GetQuery().Any(x => x.ProjectID == entity.ProjectID && x.TeamID == entity.TeamID && (x.Week == entity.Week || x.From == entity.From));
        }

        public TimeSheets GetByID(long id)
        {
            return _Repository.GetById(id);
        }

        public bool Add(TimeSheets entity)
        {
            if(CheckExist(entity))
                return false;
            if(entity.TeamID == 0 || entity.ProjectID == 0 || string.IsNullOrEmpty((entity.Week)))
                return false;
            _Repository.Add(entity);
            return true;
        }

        public bool Update(TimeSheets entity)
        {
            entity.Week = entity.From.ToString("MM/dd/yyyy") + " - " + entity.To.ToString("MM/dd/yyyy");
            _Repository.Update(entity);
            return true;
        }

        public bool SimpleUpdate(TimeSheets entity)
        {
            TimeSheets domain = _Repository.GetById(entity.Id);
            if (domain != null)
            {
                domain.ProjectID = entity.ProjectID;
                domain.TeamID = entity.TeamID;
                domain.Status = entity.Status;

                TimeSheets duplicate = _Repository.GetQuery().FirstOrDefault(p => p.TeamID == domain.TeamID && p.Id != domain.Id && p.Week == domain.Week);
                if (duplicate != null)
                {
                    throw new CustomException("Duplicate timesheet for a team");
                }
                _Repository.Update(domain);
                return true;
            }
            return false;
        }

        public bool Delete(TimeSheets entity)
        {
            TimeSheets domain = _Repository.GetById(entity.Id);
            _Repository.Delete(domain);
            return true;
        }

        public bool CopyFrom(long tmsh,TimeSheets newtmsh)
        {
            var tmshObj = _Repository.GetById(tmsh);
            if(tmshObj == null)
                return false;
            var lstTmshDetail = _TimeSheetDetailsRepository.GetQuery().Where(x => x.TransID == tmsh).ToList();
            if(lstTmshDetail != null)
            {
                foreach(var old in lstTmshDetail)
                {
                    var item = new TimeSheetDetails();
                    item.TransID = newtmsh.Id;
                    item.PerDiemFull = old.PerDiemFull;
                    item.PerDiemMeals = old.PerDiemMeals;
                    item.Notes = old.Notes;
                    item.Extension = old.Extension;
                    item.SunOTHours = old.SunOTHours;
                    item.SunSTHours = old.SunSTHours;
                    item.MonOTHours = old.MonOTHours;
                    item.MonSTHours = old.MonSTHours;
                    item.TueOTHours = old.TueOTHours;
                    item.TueSTHours = old.TueSTHours;
                    item.WebOTHours = old.WebOTHours;
                    item.WebSTHours = old.WebSTHours;
                    item.ThuOTHours = old.ThuOTHours;
                    item.ThuSTHours = old.ThuSTHours;
                    item.FirOTHours = old.FirOTHours;
                    item.FriSTHours = old.FriSTHours;
                    item.SatOTHours = old.SatOTHours;
                    item.SatSTHours = old.SatSTHours;
                    item.TotalOT = old.TotalOT;
                    item.TotalST = old.TotalST;
                    item.EmployerID = old.EmployerID;
                    item.ClassCode = old.ClassCode;
                    item.Mileage = old.Mileage;
                    item.Group = old.Group;
                    _TimeSheetDetailsRepository.Add(item);
                }
            }
            return true;
        }

        #endregion


        public TimeSheets GetLastedTimesheet(long prjID, long teamId)
        {
            return _Repository.GetAll().Where(p => p.ProjectID == prjID && p.TeamID == teamId).OrderByDescending(p => p.Ticket).FirstOrDefault();
        }

        public TimeSheets GetLastedTimesheet(long prjID)
        {
            return _Repository.GetAll().Where(p => p.ProjectID == prjID).OrderByDescending(p => p.Ticket).FirstOrDefault();
        }


        public TimeSheets GetLastedTimesheet(long prjID, string week)
        {
            return _Repository.GetAll().Where(p => p.ProjectID == prjID && p.Week == week).OrderByDescending(p => p.Ticket).FirstOrDefault();
        }
    }
}
